package org.cybzacg.encryption.factory;

import org.cybzacg.encryption.core.Encryptor;
import org.cybzacg.encryption.context.EncryptionContext;
import org.cybzacg.encryption.config.EncryptionConfig;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionType;
import org.cybzacg.encryption.exception.EncryptionException;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.function.Function;

/**
 * 加密器工厂类
 * 负责创建和管理加密器实例
 * 
 * @author encryption team
 * @version 1.0
 */
public class EncryptorFactory {
    
    private static volatile EncryptorFactory instance;
    private static final Object INSTANCE_LOCK = new Object();
    
    private final Map<EncryptionAlgorithm, Encryptor> encryptorCache;
    private final Map<EncryptionAlgorithm, Function<EncryptionContext, Encryptor>> creators;
    private final List<EncryptorFactoryListener> listeners;
    
    private EncryptorFactory() {
        this.encryptorCache = new ConcurrentHashMap<>();
        this.creators = new ConcurrentHashMap<>();
        this.listeners = new ArrayList<>();
        initializeDefaultCreators();
    }
    
    /**
     * 获取单例实例
     * 
     * @return 工厂实例
     */
    public static EncryptorFactory getInstance() {
        if (instance == null) {
            synchronized (INSTANCE_LOCK) {
                if (instance == null) {
                    instance = new EncryptorFactory();
                }
            }
        }
        return instance;
    }
    
    /**
     * 创建加密器
     * 
     * @param algorithm 算法
     * @param context 上下文
     * @return 加密器实例
     */
    public Encryptor createEncryptor(EncryptionAlgorithm algorithm, EncryptionContext context) {
        if (algorithm == null) {
            throw new IllegalArgumentException("Algorithm cannot be null");
        }
        if (context == null) {
            throw new IllegalArgumentException("Context cannot be null");
        }
        
        // 通知监听器
        notifyCreationStarted(algorithm, context);
        
        try {
            // 检查缓存
            Encryptor cached = encryptorCache.get(algorithm);
            if (cached != null && cached.supports(context)) {
                notifyCreationCompleted(algorithm, context, cached, true);
                return cached;
            }
            
            // 创建新的加密器
            Function<EncryptionContext, Encryptor> creator = creators.get(algorithm);
            if (creator == null) {
                EncryptionException ex = EncryptionException.algorithmNotSupported(
                    "No creator found for algorithm: " + algorithm, context
                );
                notifyCreationFailed(algorithm, context, ex);
                throw ex;
            }
            
            Encryptor encryptor = creator.apply(context);
            if (encryptor == null) {
                EncryptionException ex = EncryptionException.algorithmNotSupported(
                    "Creator returned null for algorithm: " + algorithm, context
                );
                notifyCreationFailed(algorithm, context, ex);
                throw ex;
            }
            
            // 初始化加密器
            encryptor.initialize(context);
            
            // 缓存加密器（如果支持共享）
            if (isShareable(encryptor)) {
                encryptorCache.put(algorithm, encryptor);
            }
            
            notifyCreationCompleted(algorithm, context, encryptor, false);
            return encryptor;
            
        } catch (Exception e) {
            EncryptionException ex = e instanceof EncryptionException ? 
                (EncryptionException) e : new EncryptionException(e.getMessage(), e);
            notifyCreationFailed(algorithm, context, ex);
            throw ex;
        }
    }
    
    /**
     * 创建加密器（使用默认配置）
     * 
     * @param algorithm 算法
     * @return 加密器实例
     */
    public Encryptor createEncryptor(EncryptionAlgorithm algorithm) {
        if (algorithm == null) {
            throw new IllegalArgumentException("Algorithm cannot be null");
        }
        
        // 检查缓存
        Encryptor cached = encryptorCache.get(algorithm);
        if (cached != null) {
            return cached;
        }
        
        // 创建新的加密器
        Function<EncryptionContext, Encryptor> creator = creators.get(algorithm);
        if (creator == null) {
            throw new EncryptionException("No creator found for algorithm: " + algorithm);
        }
        
        // 使用null上下文（简化处理）
        Encryptor encryptor = creator.apply(null);
        if (encryptor == null) {
            throw new EncryptionException("Creator returned null for algorithm: " + algorithm);
        }
        
        // 缓存加密器（如果支持共享）
        if (isShareable(encryptor)) {
            encryptorCache.put(algorithm, encryptor);
        }
        
        return encryptor;
    }
    
    /**
     * 注册加密器创建器
     * 
     * @param algorithm 算法
     * @param creator 创建器函数
     */
    public void registerCreator(EncryptionAlgorithm algorithm, Function<EncryptionContext, Encryptor> creator) {
        if (algorithm == null) {
            throw new IllegalArgumentException("Algorithm cannot be null");
        }
        if (creator == null) {
            throw new IllegalArgumentException("Creator cannot be null");
        }
        
        creators.put(algorithm, creator);
        notifyCreatorRegistered(algorithm);
    }
    
    /**
     * 注册加密器类
     * 
     * @param algorithm 算法
     * @param encryptorClass 加密器类
     */
    public void registerEncryptorClass(EncryptionAlgorithm algorithm, Class<? extends Encryptor> encryptorClass) {
        registerCreator(algorithm, context -> {
            try {
                return encryptorClass.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new EncryptionException("Failed to create encryptor instance: " + e.getMessage(), e);
            }
        });
    }
    
    /**
     * 注册加密器实例
     * 
     * @param algorithm 算法
     * @param encryptor 加密器实例
     */
    public void registerEncryptorInstance(EncryptionAlgorithm algorithm, Encryptor encryptor) {
        if (algorithm == null) {
            throw new IllegalArgumentException("Algorithm cannot be null");
        }
        if (encryptor == null) {
            throw new IllegalArgumentException("Encryptor cannot be null");
        }
        
        encryptorCache.put(algorithm, encryptor);
        notifyEncryptorRegistered(algorithm, encryptor);
    }
    
    /**
     * 检查是否支持指定算法
     * 
     * @param algorithm 算法
     * @return 是否支持
     */
    public boolean isSupported(EncryptionAlgorithm algorithm) {
        return creators.containsKey(algorithm) || encryptorCache.containsKey(algorithm);
    }
    
    /**
     * 获取所有支持的算法
     * 
     * @return 支持的算法列表
     */
    public List<EncryptionAlgorithm> getSupportedAlgorithms() {
        List<EncryptionAlgorithm> algorithms = new ArrayList<>();
        algorithms.addAll(creators.keySet());
        algorithms.addAll(encryptorCache.keySet());
        return algorithms;
    }
    
    /**
     * 获取按类型分组的算法
     * 
     * @param type 加密类型
     * @return 算法列表
     */
    public List<EncryptionAlgorithm> getAlgorithmsByType(EncryptionType type) {
        List<EncryptionAlgorithm> result = new ArrayList<>();
        for (EncryptionAlgorithm algorithm : getSupportedAlgorithms()) {
            if (algorithm.getType() == type) {
                result.add(algorithm);
            }
        }
        return result;
    }
    
    /**
     * 清除缓存
     * 
     * @param algorithm 算法，如果为null则清除所有缓存
     */
    public void clearCache(EncryptionAlgorithm algorithm) {
        if (algorithm == null) {
            encryptorCache.clear();
            notifyCacheCleared(null);
        } else {
            encryptorCache.remove(algorithm);
            notifyCacheCleared(algorithm);
        }
    }
    
    /**
     * 添加工厂监听器
     * 
     * @param listener 监听器
     */
    public void addListener(EncryptorFactoryListener listener) {
        if (listener != null) {
            listeners.add(listener);
        }
    }
    
    /**
     * 移除工厂监听器
     * 
     * @param listener 监听器
     */
    public void removeListener(EncryptorFactoryListener listener) {
        listeners.remove(listener);
    }
    
    /**
     * 获取工厂统计信息
     * 
     * @return 统计信息
     */
    public FactoryStatistics getStatistics() {
        return new FactoryStatistics(
            creators.size(),
            encryptorCache.size(),
            getSupportedAlgorithms()
        );
    }
    
    /**
     * 初始化默认创建器
     */
    private void initializeDefaultCreators() {
        // 这里可以注册一些默认的加密器创建器
        // 实际的加密器实现将在后续步骤中添加
    }
    
    /**
     * 检查加密器是否可共享
     */
    private boolean isShareable(Encryptor encryptor) {
        // 简单的共享策略：无状态的加密器可以共享
        // 实际实现中可以根据加密器的特性来判断
        return true;
    }
    
    /**
     * 通知创建开始
     */
    private void notifyCreationStarted(EncryptionAlgorithm algorithm, EncryptionContext context) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onEncryptorCreationStarted(algorithm, context);
            } catch (Exception e) {
                // 监听器异常不应该影响主要流程
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 通知创建完成
     */
    private void notifyCreationCompleted(EncryptionAlgorithm algorithm, EncryptionContext context, 
                                       Encryptor encryptor, boolean fromCache) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onEncryptorCreationCompleted(algorithm, context, encryptor, fromCache);
            } catch (Exception e) {
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 通知创建失败
     */
    private void notifyCreationFailed(EncryptionAlgorithm algorithm, EncryptionContext context, Exception exception) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onEncryptorCreationFailed(algorithm, context, exception);
            } catch (Exception e) {
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 通知创建器注册
     */
    private void notifyCreatorRegistered(EncryptionAlgorithm algorithm) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onCreatorRegistered(algorithm);
            } catch (Exception e) {
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 通知加密器注册
     */
    private void notifyEncryptorRegistered(EncryptionAlgorithm algorithm, Encryptor encryptor) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onEncryptorRegistered(algorithm, encryptor);
            } catch (Exception e) {
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 通知缓存清除
     */
    private void notifyCacheCleared(EncryptionAlgorithm algorithm) {
        for (EncryptorFactoryListener listener : listeners) {
            try {
                listener.onCacheCleared(algorithm);
            } catch (Exception e) {
                System.err.println("Factory listener error: " + e.getMessage());
            }
        }
    }
    
    /**
     * 工厂监听器接口
     */
    public interface EncryptorFactoryListener {
        default void onEncryptorCreationStarted(EncryptionAlgorithm algorithm, EncryptionContext context) {}
        default void onEncryptorCreationCompleted(EncryptionAlgorithm algorithm, EncryptionContext context, 
                                                 Encryptor encryptor, boolean fromCache) {}
        default void onEncryptorCreationFailed(EncryptionAlgorithm algorithm, EncryptionContext context, Exception exception) {}
        default void onCreatorRegistered(EncryptionAlgorithm algorithm) {}
        default void onEncryptorRegistered(EncryptionAlgorithm algorithm, Encryptor encryptor) {}
        default void onCacheCleared(EncryptionAlgorithm algorithm) {}
    }
}
